<!DOCTYPE html>
<html>
<head>
<title>js.js Callbacks Testing</title>
<link href="../bootstrap.min.css" rel="stylesheet" >
<script type="text/javascript" src="../jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../libjs.O2.min.js"></script>
<script type="text/javascript" src="../common.js"></script>
<script type="text/javascript">

    function start_jsjs() {
        var jsObjs = JSJS.Init();

        // 1 int
        
        function callbackInt(func) {
            reportMessage("callbackInt");
            var jsvalout = JSJS.CreateJSVal(jsObjs.cx, func, JSJS.Types.objPtr);
            JSJS.CallFunctionValue(jsObjs.cx, jsObjs.glob, jsvalout, [JSJS.Types.i32], [55]);
        }
        function verifyInt(val) {
            reportMessage("verifyInt");
            reportMessage("int val should be 55: " + val);
            assert(val == 55);
            return 55;
        }
        var wrappedCallbackInt = JSJS.wrapFunction({
            func : callbackInt,
            args : [JSJS.Types.objPtr],
            returns : null
        });
        var wrappedVerifyInt = JSJS.wrapFunction({
            func : verifyInt,
            args : [JSJS.Types.i32],
            returns : JSJS.Types.i32
        });
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "callbackInt", wrappedCallbackInt, 1, 0);
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "verifyInt", wrappedVerifyInt, 1, 0);
        
        
        
        // 1 string 
        
        function callbackString(func) {
            reportMessage("callbackString");
            reportMessage(func);
            var jsvalout = JSJS.CreateJSVal(jsObjs.cx, func, JSJS.Types.objPtr);
            JSJS.CallFunctionValue(jsObjs.cx, jsObjs.glob, jsvalout, [JSJS.Types.charPtr], ["blah"]);
        }
        function verifyString(s) {
            reportMessage("verifyString");
            reportMessage("s val should be 'blah': " + s);
            assert(s == 'blah');
            return "blah";
        }
        var wrappedCallbackString = JSJS.wrapFunction({
            func : callbackString,
            args : [JSJS.Types.objPtr],
            returns : null
        });
        var wrappedVerifyString = JSJS.wrapFunction({
            func : verifyString,
            args : [JSJS.Types.charPtr],
            returns : JSJS.Types.charPtr
        });
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "callbackString", wrappedCallbackString, 1, 0);
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "verifyString", wrappedVerifyString, 1, 0);
        
        
        // 1 object
        
        function objGetProperty(propName) {
            reportMessage("obj get property " + propName);
            switch(propName) {
            case "tester":
                return {'type': JSJS.Types.charPtr, 'val': "hello"};
                break;
            }
            throw "Not Implemented obj prop - " + propName;
        }
        var jsObjClass = JSJS.CreateClass(JSJS['JSCLASS_GLOBAL_FLAGS'],
                JSJS['PropertyStub'],
                JSJS['PropertyStub'],
                JSJS.wrapGetter(objGetProperty, JSJS.Types.bool),
                JSJS['StrictPropertyStub'],
                JSJS['EnumerateStub'],
                JSJS['ResolveStub'],
                JSJS['ConvertStub'],
                JSJS['FinalizeStub']);
        var jsObj = JSJS.NewObject(jsObjs.cx, jsObjClass, 0, 0);
        
        function callbackObject(func) {
            reportMessage("callbackObject");
            reportMessage(func);
            var jsvalout = JSJS.CreateJSVal(jsObjs.cx, func, JSJS.Types.objPtr);
            JSJS.CallFunctionValue(jsObjs.cx, jsObjs.glob, jsvalout, [JSJS.Types.objPtr], [jsObj]);
        }
        function verifyObject(o, b) {
            reportMessage("verifyObject");
            reportMessage("obj val should be " + jsObj + ": " + o);
            assert(o == jsObj);
            reportMessage("obj bool should be 'true': " + b);
            assert(b == true);
        }
        var wrappedCallbackObject = JSJS.wrapFunction({
            func : callbackObject,
            args : [JSJS.Types.objPtr],
            returns : null
        });
        var wrappedVerifyObject = JSJS.wrapFunction({
            func : verifyObject,
            args : [JSJS.Types.objPtr, JSJS.Types.bool],
            returns : null
        });
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "callbackObject", wrappedCallbackObject, 1, 0);
        JSJS.DefineFunction(jsObjs.cx, jsObjs.glob, "verifyObject", wrappedVerifyObject, 2, 0);
        
        var srcTest = "callbackInt(function(x) { verifyInt(verifyInt(x)); });" + 
                      "callbackString(function(x) { verifyString(verifyString(x)); });" + 
                      "callbackObject(function(x) {verifyObject(x, x.tester == 'hello');})"
                      ;
        JSJS.EvaluateScript(jsObjs.cx, jsObjs.glob, srcTest);
    }

    window.onload = start_jsjs;
</script>
</head>
<body>
  <div class="container">
    <div class="page-header">
      <h1>js.js Callback Testing</h1>
    </div>
    <p>Demonstrates two-way communication with different argument types. Shows integers, strings, and objects
       being passed back and forth between sandbox and native JavaScript space.</p>
    <pre id="console_log"></pre>
  </div>
</body>
</html>
